using System;
using System.Xml;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace BrianLyttle.Samples.WinForms
{
    public partial class CrashDetailsDialog : Form
    {
        private const string xmlNameSpace = "http://www.crashmanager.com/version/0.1/";
        private List<CrashDataItem> basicInfo;
        private string advInfo;

        public CrashDetailsDialog(List<CrashDataItem> BasicInfo, string AdvancedInfo)
        {
            basicInfo = BasicInfo;
            advInfo = AdvancedInfo;

            InitializeComponent();
            InitializeDialog();
        }

        /// <summary>
        /// Performs setup of the crash information in the dialog.
        /// </summary>
        private void InitializeDialog()
        {
            txtMoreInfo.Text = advInfo;

            foreach(CrashDataItem item in basicInfo)
            {
                AddRow(item.Name, item.Value);
            }
        }

        /// <summary>
        /// Adds a row to the basic crash information listview control.
        /// </summary>
        /// <param name="Name">Name of item.</param>
        /// <param name="Value">Value of item.</param>
        private void AddRow(string Name, string Value)
        {
            lvBasicInfo.Items.Add(CreateRow(Name, Value));
        }

        /// <summary>
        /// Creates a ListViewItem with name/value pair.
        /// </summary>
        /// <param name="Name">Name of item.</param>
        /// <param name="Value">Value of item.</param>
        private ListViewItem CreateRow(string Name, string Value)
        {
            ListViewItem item = new ListViewItem(Name);
            item.SubItems.Add(new ListViewItem.ListViewSubItem(item, Value));
            return item;
        }

        /// <summary>
        /// Closes the details dialog and returns to the main dialog.
        /// </summary>
        private void btnClose_Click(object sender, EventArgs e)
        {
            Close();
        }

        /// <summary>
        /// Allows user to save the basic crash information and stack trace to
        /// a location as an XML document. XML document can be manually
        /// loaded in CrashManager Reporter.
        /// </summary>
        private void btnSave_Click(object sender, EventArgs e)
        {
            saveFileDialog.Filter = "XML Files (*.xml)|*.xml|All Files (*.*)|*.*";
            saveFileDialog.Title = "Save As";

            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                SaveCrashAsXml(saveFileDialog.FileName, basicInfo, advInfo);
            }
        }

        /// <summary>
        /// Saves the crash report data to an XML file.
        /// </summary>
        /// <param name="FileName">String specifying complete path to save XML file.</param>
        /// <param name="BasicInfo">List of basic diagnostic name/value pairs.</param>
        /// <param name="StackTrace">String representation of StackTrace.</param>
        private void SaveCrashAsXml(string FileName, List<CrashDataItem> BasicInfo, string StackTrace)
        {
            try
            {
                using (XmlTextWriter writer = new XmlTextWriter(FileName, Encoding.UTF8))
                {
                    // Pretty print the XML
                    writer.Formatting = Formatting.Indented;
                    // start document
                    writer.WriteStartDocument();

                    // root node
                    writer.WriteStartElement("crashreport", xmlNameSpace);

                    // basic information
                    WriteBasicInformation(BasicInfo, writer);

                    // stack trace
                    WriteStackTrace(StackTrace, writer);

                    // end document
                    writer.WriteFullEndElement();
                }

            }
            catch (Exception Ex)
            {
                MessageBox.Show(Ex.Message);
            }
        }

        /// <summary>
        /// Creates an element called 'stacktrace' containing the crash stack trace.
        /// </summary>
        /// <param name="StackTrace">String representation of stack trace.</param>
        /// <param name="Writer">XmlTextWriter to write to.</param>
        private static void WriteStackTrace(string StackTrace, XmlTextWriter Writer)
        {
            Writer.WriteElementString("stacktrace", StackTrace);
        }

        /// <summary>
        /// Creates an element called 'diagnostics' with elements containing the basic information
        /// in name/value pairs
        /// </summary>
        /// <param name="BasicInfo">List of basic crash data items.</param>
        /// <param name="Writer">XmlTextWriter to write to.</param>
        private static void WriteBasicInformation(List<CrashDataItem> BasicInfo, XmlTextWriter Writer)
        {
            Writer.WriteStartElement("diagnostics");
            foreach (CrashDataItem item in BasicInfo)
            {
                Writer.WriteStartElement("info");
                Writer.WriteAttributeString("name", item.Name);
                Writer.WriteAttributeString("value", item.Value);
                Writer.WriteEndElement();	
            }
            Writer.WriteFullEndElement();
        }
    }
}